﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;

using Fuse8.ContentManagementFramework.SystemFacade.Extensions;
using Fuse8.ContentManagementFramework.SystemFacade.Globalization;

namespace Fuse8.ContentManagementFramework.SystemFacade.Utilities
{
    public static class EnumUtility<T>
    {
        /// <summary>
        /// Get enum value by it's integer equivalent
        /// </summary>
        /// <param name="intVal"></param>
        /// <returns></returns>
        public static T GetValue(int intVal)
        {
            return (T)Enum.ToObject(typeof(T), intVal);
        }

        /// <summary>
        /// Get enum value by it's integer equivalent
        /// </summary>
        /// <param name="intNullableVal"></param>
        /// <returns></returns>
        public static T GetValue(int? intNullableVal)
        {
            int intVal = intNullableVal ?? 0;

            return GetValue(intVal);
        }

        /// <summary>
        /// Get enum value by it's integer equivalent or default if not founded
        /// </summary>
        /// <param name="intVal"></param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public static T GetValueOrDefault(int intVal, T defaultValue)
        {
            T result = defaultValue;

            if (Enum.GetName(typeof(T), intVal) != null)
            {
                result = (T)Enum.ToObject(typeof(T), intVal);
            }

            return result;
        }

        /// <summary>
        /// Get enum value by it's description
        /// </summary>
        /// <param name="description"></param>
        /// <returns></returns>
        public static T GetEnumValue(string description)
        {
            var descriptions = GetDescriptionsAndNames();

            //NotDefined by default
            T result = GetValue(0);

            if (descriptions.ContainsKey(description))
            {
                result = (T)Enum.Parse(typeof(T), descriptions[description]);
            }

            return result;
        }

        /// <summary>
        /// Get all enum's values
        /// </summary>
        /// <returns></returns>
        public static IList<T> GetValues()
        {
            return Enum.GetValues(typeof(T)).Cast<T>().ToList();
        }

        /// <summary>
        /// Get all enum's descriptions
        /// </summary>
        /// <returns></returns>
        public static IList<string> GetDescriptions()
        {
            var descriptions = new List<string>();

            foreach (Enum value in Enum.GetValues(typeof(T)))
            {
                if (value.ToString() != "NotDefined")
                {
                    descriptions.Add(value.GetDescription());
                }
            }

            return descriptions;
        }

        /// <summary>
        /// Get all enum's values and names
        /// </summary>
        /// <returns></returns>
        public static Dictionary<int, string> GetValuesAndNames()
        {
            return Enum.GetValues(typeof(T))
                .Cast<T>()
                .ToDictionary(item => (int)Enum.Parse(typeof(T), item.ToString()), item => item.ToString());
        }

        /// <summary>
        /// Get all enum's values and names
        /// </summary>
        /// <returns></returns>
        public static Dictionary<int, string> GetValuesAndDescriptions()
        {
            var dictionary = new Dictionary<int, string>();

            foreach (Enum value in Enum.GetValues(typeof(T)))
            {
                if (value.ToString() != "NotDefined")
                {
                    dictionary.Add((int)Enum.Parse(typeof(T), value.ToString()), value.GetDescription());
                }
            }

            return dictionary;
        }   

        /// <summary>
        /// Get all enum's names and descriptions
        /// </summary>
        /// <returns></returns>
        public static Dictionary<string, string> GetNamesAndDescriptions(bool localized = false)
        {
            var dictionary = new Dictionary<string, string>();

            foreach (Enum value in Enum.GetValues(typeof(T)))
            {
                if (value.ToString() != "NotDefined")
                {
                    var description = value.GetDescription();
                    if (localized)
                    {
                        description =
                            GlobalizationFacade.Current.WithDomain("cms_Common", CultureInfo.CurrentUICulture)
                                .GetText(description);
                    }
                    dictionary.Add(value.ToString(), description);
                }
            }

            return dictionary;
        }

        /// <summary>
        /// Get all enum's descriptions and names
        /// </summary>
        /// <returns></returns>
        public static Dictionary<string, string> GetDescriptionsAndNames()
        {
            var dictionary = new Dictionary<string, string>();

            foreach (Enum value in Enum.GetValues(typeof(T)))
            {
                if (value.ToString() != "NotDefined")
                {
                    dictionary.Add(value.GetDescription(), value.ToString());
                }
            }

            return dictionary;
        }
    }
}
